package org.bhf.jsp;

/**
 * Copyright (c) 2007, Blue Hole Software. All rights reserved.
 * Code licensed under the Apache 2.0 License:
 * http://www.apache.org/licenses/
 */

import com.google.inject.Injector;
import org.bhf.facilities.ProjectInjectors;
import org.bhf.service.CSRTokenFacility;
import org.bhf.service.Service;
import org.bhf.service.ServiceGroup;
import org.bhf.service.ServiceGroupInfo;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;
import java.io.IOException;
import java.io.Writer;

/**
 * Create a CSRF token.
 * @exclude
 */
public class TokenTag extends TagSupport
{
    private static final long serialVersionUID = -1676505332940116162L;

    /** Reference to the Component object, must not be null */
    protected Class<? extends Service>  service;

    //
    // Properties
    //

    /**
     * Sets the Service object, by class.
     *
     * @param service The Service object.
     */
    @SuppressWarnings( "unchecked" )
    public void setService( final String service )
    {
        try
        {
            this.service = (Class<? extends Service>) Class.forName( service, false, Thread.currentThread().getContextClassLoader() );
        }
        catch( ClassNotFoundException cnfe )
        {
            throw new RuntimeException( cnfe );
        }
    }

    /**
     * Render the service declaration and initialization.
     *
     * @throws javax.servlet.jsp.JspException If a JSP exception has occurred.
     *
     * @return <code>Tag.EVAL_BODY_INCLUDE</code>.
     */
    @Override
    public int doStartTag()
        throws JspException
    {
        try
        {
            final Injector                  injector        = ProjectInjectors.getProjectInjector();
            final Writer                    writer          = pageContext.getOut();
            final String                    serviceName     = Service.Util.getName( service );
            final ServiceGroup              serviceGroup    = ServiceGroup.getServiceGroupForService( service );
            final CSRTokenFacility tokens          = injector.getInstance( CSRTokenFacility.class );

            if( serviceName == null )
                throw new JspException( "Service class " + service.getName() + " does not have a ServiceName annotation" );
            if( serviceGroup == null )
                throw new JspException( "The ServiceGroup for " + service.getName() + " has not yet been loaded. Make sure to initialize the ControllerServlet on startup." );

            final String moduleName = ServiceGroupInfo.Util.getName( serviceGroup.getClass() );
            if( moduleName == null )
                throw new JspException( "ServiceGroup class " + serviceGroup.getClass().getName() + " does not have a ServiceGroupInfo annotation" );

            writer.write( tokens.getToken( ServiceGroupInfo.Util.getName( serviceGroup.getClass() ), serviceName ) );
        }
        catch( IOException e )
        {
            throw new JspException( e );
        }

        return Tag.EVAL_BODY_INCLUDE;
    }
}